home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C++ / Libraries / KPlib 1.2.1 / KPString.h < prev   
Encoding:
Text File  |  1994-11-07  |  9.3 KB  |  269 lines  |  [TEXT/R*ch]

  1. // A module of KPlib v1.2.1.
  2. // Written by Keith Pomakis during the summer of 1994.
  3. // Released to the public domain on October 10, 1994.
  4.  
  5. #ifndef KP_STRING_DEFINED
  6. #define KP_STRING_DEFINED
  7.  
  8. #include <iostream.h>
  9. #include <strstream.h>
  10. #include <string.h>
  11. #include "KPbasic.h"
  12.  
  13. // This class uses reference counting and copy-on-write semantics to insure
  14. // that it as efficient as possible.
  15.  
  16. // All indexes are zero-based.  For all functions that accept an index, a
  17. // negative index specifies an index from the right of the string.  Also,
  18. // for all functions that accept a length, a length of -1 specifies the rest
  19. // of the string.
  20.  
  21. // "KPList.h" is included further on down to insure that it isn't defined
  22. // before KPString, so that KPList<KPString> will be considered a complete
  23. // type in the following definition of KPString.  This is probably a
  24. // g++-specific problem.
  25.  
  26. template <class Element> class KPList;
  27.  
  28. class KPString;
  29.  
  30. // A KPString can be used as a sink for concatenating the output of other
  31. // classes or intrinsic data types.  For example:
  32. //
  33. //    KPString s;
  34. //    int answer;
  35. //    s << "The answer is " << answer;
  36. //    /* s now contains "The answer is 42" */
  37.  
  38. template <class Type> inline KPString &operator<<(KPString &s, const Type &x);
  39.  
  40. class KPString {
  41.         friend istream &operator>>(istream &stream, KPString &s);
  42.         inline friend ostream &operator<<(ostream &stream, const KPString &s);
  43.         friend KPString operator+(const char *s1, const KPString &s2);
  44.         inline friend bool operator==(const char *s1, const KPString &s2);
  45.         inline friend bool operator<(const char *s1, const KPString &s2);
  46.         inline friend bool operator<=(const char *s1, const KPString &s2);
  47.         inline friend bool operator>(const char *s1, const KPString &s2);
  48.         inline friend bool operator>=(const char *s1, const KPString &s2);
  49.         inline friend bool operator!=(const char *s1, const KPString &s2);
  50.         inline friend void swap(KPString &s1, KPString &s2);
  51.     public:
  52.         KPString();
  53.         KPString(const KPString &s);
  54.         KPString(const char *s);
  55.         KPString(char c, int n = 1);
  56.         ~KPString();
  57.         operator const char *() const;
  58.         char &operator[](int index);
  59.         char operator[](int index) const;
  60.         KPString &operator=(const KPString &s);
  61.         KPString &operator=(const char *s);
  62.         KPString operator+(const KPString &s) const;
  63.         KPString operator+(const char *s) const;
  64.         bool operator==(const KPString &s) const;
  65.         bool operator==(const char *s) const;
  66.         bool operator<(const KPString &s) const;
  67.         bool operator<(const char *s) const;
  68.         bool operator<=(const KPString &s) const;
  69.         bool operator<=(const char *s) const;
  70.         bool operator>(const KPString &s) const;
  71.         bool operator>(const char *s) const;
  72.         bool operator>=(const KPString &s) const;
  73.         bool operator>=(const char *s) const;
  74.         bool operator!=(const KPString &s) const;
  75.         bool operator!=(const char *s) const;
  76.         KPString &operator+=(const KPString &s);
  77.         KPString &operator+=(const char *s);
  78.         int length() const;
  79.         bool is_empty() const;
  80.         KPString substr(int index = 0, int len = -1) const;
  81.         KPString copy() const;
  82.         KPString &cut(int index = 0, int len = -1);
  83.         KPString &replace_substr(const KPString &s, int index = 0, int len=-1);
  84.         KPString &replace_substr(const char *s, int index = 0, int len = -1);
  85.         KPString &insert(const KPString &s, int index = 0);
  86.         KPString &insert(const char *s, int index = 0);
  87.         KPString &to_upper();
  88.         KPString &to_lower();
  89.         KPString &clear();
  90.         int index_of(const KPString &s, int start_index = 0) const;
  91.         int index_of(const char *s, int start_index = 0) const;
  92.         int index_of(char c, int start_index = 0) const;
  93.         bool contains(const KPString &s) const;
  94.         bool contains(const char *s) const;
  95.         bool contains(char c) const;
  96.         KPList<KPString> tokens(const char *separators=" \t\n") const;
  97.         KPList<KPString> tokens(char separator) const;
  98.         KPString &read_line(istream &stream);
  99.         KPString &read_token(istream &stream, const char *separators=" \t\n");
  100.  
  101.         static const int max_token_size;
  102.         static const int max_line_size;
  103.  
  104.     protected:
  105.         static void invalid_args_error(const char *fname);
  106.         static void invalid_index_error(const char *fname);
  107.         class Data {
  108.             public:
  109.                 Data(): ref_count(0), length(0) { chars[0] = '\0'; }
  110.                 unsigned int ref_count;
  111.                 int length;
  112.                 char chars[1];
  113.         };
  114.         static Data *new_data(int length);
  115.         void replace_data(int length);
  116.         void replace_data(Data *data);
  117.         void make_unique();
  118.         char *chars();
  119.         const char *chars() const;
  120.     protected:
  121.         Data *my_data;
  122.         static Data null_data;
  123. };
  124.  
  125. /***************************************************************************/
  126.  
  127. #include "KPList.h"
  128.  
  129. inline char *KPString::chars()
  130. { return my_data->chars; }
  131.  
  132. inline const char *KPString::chars() const
  133. { return my_data->chars; }
  134.  
  135. inline ostream &operator<<(ostream &stream, const KPString &s)
  136. { stream << s.chars(); return stream; }
  137.  
  138. inline bool operator==(const char *s1, const KPString &s2)
  139. { return (strcmp(s1, s2.chars()) == 0); }
  140.  
  141. inline bool operator<(const char *s1, const KPString &s2)
  142. { return (strcmp(s1, s2.chars()) < 0); }
  143.  
  144. inline bool operator<=(const char *s1, const KPString &s2)
  145. { return (strcmp(s1, s2.chars()) <= 0); }
  146.  
  147. inline bool operator>(const char *s1, const KPString &s2)
  148. { return (strcmp(s1, s2.chars()) > 0); }
  149.  
  150. inline bool operator>=(const char *s1, const KPString &s2)
  151. { return (strcmp(s1, s2.chars()) >= 0); }
  152.  
  153. inline bool operator!=(const char *s1, const KPString &s2)
  154. { return (strcmp(s1, s2.chars()) != 0); }
  155.  
  156. inline void swap(KPString &s1, KPString &s2)
  157. { swap(s1.my_data, s2.my_data); }
  158.  
  159. template <class Type>
  160. inline KPString &operator<<(KPString &s, const Type &x)
  161. { ostrstream sink; sink << x; s += sink.str(); return s; }
  162.  
  163. inline KPString::KPString(): my_data(&null_data)
  164. { /* do nothing */ }
  165.  
  166. inline KPString::KPString(const KPString &s): my_data(&null_data)
  167. { replace_data(s.my_data); }
  168.  
  169. inline KPString::KPString(const char *s): my_data(&null_data)
  170. { const int length = ::strlen(s); replace_data(length);
  171.   ::memcpy(chars(), s, length); }
  172.  
  173. inline KPString::KPString(char c, int n): my_data(&null_data)
  174. { replace_data(n); ::memset(chars(), c, n); }
  175.  
  176. inline KPString::~KPString()
  177. { if (my_data != &null_data && --my_data->ref_count == 0) free(my_data); }
  178.  
  179. inline KPString::operator const char *() const
  180. { return my_data->chars; }
  181.  
  182. inline char &KPString::operator[](int index)
  183. { if (index < 0) index += length();
  184.   if (index < 0 || index >= length()) invalid_index_error("operator[]");
  185.   make_unique(); return chars()[index]; }
  186.  
  187. inline char KPString::operator[](int index) const
  188. { if (index < 0) index += length();
  189.   if (index < 0 || index >= length()) invalid_index_error("operator[]");
  190.   return chars()[index]; }
  191.  
  192. inline KPString &KPString::operator=(const KPString &s)
  193. { replace_data(s.my_data); return *this; }
  194.  
  195. inline KPString &KPString::operator=(const char *s)
  196. { const int length = ::strlen(s); replace_data(length);
  197.   ::memcpy(chars(), s, length); return *this; }
  198.  
  199.  
  200. inline bool KPString::operator==(const KPString &s) const
  201. { return (length() == s.length()) &&
  202.          (memcmp(chars(), s.chars(), length()) == 0); }
  203.  
  204. inline bool KPString::operator==(const char *s) const
  205. { return (strcmp(chars(), s) == 0); }
  206.  
  207. inline bool KPString::operator<(const KPString &s) const
  208. { return (strcmp(chars(), s.chars()) < 0); }
  209.  
  210. inline bool KPString::operator<(const char *s) const
  211. { return (strcmp(chars(), s) < 0); }
  212.  
  213. inline bool KPString::operator<=(const KPString &s) const
  214. { return (strcmp(chars(), s.chars()) <= 0); }
  215.  
  216. inline bool KPString::operator<=(const char *s) const
  217. { return (strcmp(chars(), s) <= 0); }
  218.  
  219. inline bool KPString::operator>(const KPString &s) const
  220. { return (strcmp(chars(), s.chars()) > 0); }
  221.  
  222. inline bool KPString::operator>(const char *s) const
  223. { return (strcmp(chars(), s) > 0); }
  224.  
  225. inline bool KPString::operator>=(const KPString &s) const
  226. { return (strcmp(chars(), s.chars()) >= 0); }
  227.  
  228. inline bool KPString::operator>=(const char *s) const
  229. { return (strcmp(chars(), s) >= 0); }
  230.  
  231. inline bool KPString::operator!=(const KPString &s) const
  232. { return (length() != s.length()) ||
  233.          (memcmp(chars(), s.chars(), length()) != 0); }
  234.  
  235. inline bool KPString::operator!=(const char *s) const
  236. { return (strcmp(chars(), s) != 0); }
  237.  
  238. inline KPString &KPString::operator+=(const KPString &s)
  239. { *this = *this + s; return *this; }
  240.  
  241. inline KPString &KPString::operator+=(const char *s)
  242. { *this = *this + s; return *this; }
  243.  
  244. inline int KPString::length() const
  245. { return my_data->length; }
  246.  
  247. inline bool KPString::is_empty() const
  248. { return my_data == &null_data; }
  249.  
  250. inline KPString KPString::copy() const
  251. { KPString newstring(*this); return newstring; }
  252.  
  253. inline KPString &KPString::clear()
  254. { replace_data(0); return *this; }
  255.  
  256. inline int KPString::index_of(const KPString &s, int start_index) const
  257. { return index_of(s.chars(), start_index); }
  258.  
  259. inline bool KPString::contains(const KPString &s) const
  260. { return (index_of(s, 0) >= 0); }
  261.  
  262. inline bool KPString::contains(const char *s) const
  263. { return (index_of(s, 0) >= 0); }
  264.  
  265. inline bool KPString::contains(char c) const
  266. { return (index_of(c, 0) >= 0); }
  267.  
  268. #endif /* KP_STRING_DEFINED */
  269.